#import "EspBlufiPlugin.h"
#import "BlufiClient.h"
#import "ESPPeripheral.h"
#import "EspBlufiCode.h"


@interface EspBlufiPlugin ()<BlufiDelegate, CBCentralManagerDelegate, CBPeripheralDelegate, BlufiDelegate>
// 中心管理者(管理设备的扫描和连接)
@property (nonatomic, strong) CBCentralManager *centralManager;

// 外设状态
@property (nonatomic, assign) CBManagerState peripheralState;

//@property(nonatomic, strong) ESPFBYBLEHelper *espFBYBleHelper;

///过滤
@property(nonatomic, strong) NSString *filterContent;

// 设备列表
@property(nonatomic, copy) NSMutableDictionary *peripheralDictionary;
// 选定的设备
@property(strong, nonatomic)ESPPeripheral *device;

@property(strong, nonatomic)BlufiClient *blufiClient;

@property(assign, atomic)BOOL connected;

// 正在扫描状态
@property(assign, atomic)BOOL isScaning;
@end

@implementation EspBlufiPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel* channel = [FlutterMethodChannel
                                     methodChannelWithName:@"esp_blufi"
                                     binaryMessenger:[registrar messenger]];
    EspBlufiPlugin* instance = [[EspBlufiPlugin alloc] init];
    instance.channel = channel;
    [registrar addMethodCallDelegate:instance channel:channel];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    if ([@"getPlatformVersion" isEqualToString:call.method]) {
        result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
    } else if ([@"isBluetoothEnabled" isEqualToString:call.method]){
        [self isBluetoothEnabled:result];
    } else if ([@"scan" isEqualToString:call.method]){
        [self startScan:call.arguments[@"filter"] result:result];
    } else if ([@"stopScan" isEqualToString:call.method]){
        [self stopScan];
    } else if ([@"connectDevice" isEqualToString:call.method]){
        [self connectDevice:_peripheralDictionary[call.arguments[@"address"]]];
    } else if ([@"configure" isEqualToString:call.method]){
        [self configure:call.arguments[@"ssid"] password:call.arguments[@"password"]];
    }else if ([@"requestDeviceWifiScan" isEqualToString:call.method]){
        [self requestDeviceWifiScan];
    } else if ([@"requestDeviceVersion" isEqualToString:call.method]){
        [self requestDeviceVersion];
    } else if ([@"requestDeviceStatus" isEqualToString:call.method]){
        [self requestDeviceStatus];
    } else if ([@"requestCloseConnection" isEqualToString:call.method]){
        [self requestCloseConnection];
    }
    else {
        result(FlutterMethodNotImplemented);
    }
}

FlutterResult bluetoothEnabledResult;

///蓝牙开关判断
- (void) isBluetoothEnabled: (FlutterResult) result {
    bluetoothEnabledResult = result;
    if (_centralManager == nil){
        _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    }
}

- (void) startScan:(NSString*) filter result: (FlutterResult) result{
    if (_centralManager == nil){
        _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    }
    
    if (!_peripheralDictionary) {
        _peripheralDictionary = [[NSMutableDictionary alloc] init];
    } else {
        [_peripheralDictionary removeAllObjects];
    }
    self.filterContent = filter;
    _isScaning = true;
    if (_peripheralState == CBManagerStatePoweredOn)
    {
        [self.centralManager scanForPeripheralsWithServices:nil options:nil];
        result(@(YES));
    } else {
        result(@(NO));
    }
}
- (void) stopScan {
    _isScaning = false;
    if (!_centralManager){
        return;
    }
    [_centralManager stopScan];
}

- (void) connectDevice: (ESPPeripheral*) peripheral{
    _isScaning = false;
    
    _device = peripheral;
    if (_blufiClient) {
        [_blufiClient close];
        _blufiClient = nil;
    }
    _blufiClient = [[BlufiClient alloc] init];
    //这个有必要吗?
    _blufiClient.centralManagerDelete = self;
    _blufiClient.peripheralDelegate = self;
    _blufiClient.blufiDelegate = self;
    [_blufiClient connect:_device.uuid.UUIDString];
}

- (void) configure: (NSString*) ssid password: (NSString*) password {
    BlufiConfigureParams *params = [[BlufiConfigureParams alloc] init];
    params.opMode = OpModeSta;
    params.staSsid = ssid;
    params.staPassword = password;
    
    [_blufiClient configure:params];
}

- (void) requestDeviceWifiScan {
    [_blufiClient requestDeviceScan];
}

- (void) requestDeviceVersion{
    [_blufiClient requestDeviceVersion];
}


- (void) requestDeviceStatus{
    [_blufiClient requestDeviceStatus];
}

- (void) requestCloseConnection{
    [_blufiClient requestCloseConnection];
}


#pragma mark - CBCentralManagerDelegate

/**
 扫描到设备
 
 @param central 中心管理者
 @param peripheral 扫描到的设备
 @param advertisementData 广告信息
 @param RSSI 信号强度
 */
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    //BlufiClient 扫描设备时不往flutter端发送设备信息
    if (!_isScaning){
        return;
    }
//        NSLog(@"扫描到设备");
//    NSLog([advertisementData description]);
    ESPPeripheral *espPeripheral = [[ESPPeripheral alloc] initWithPeripheral:peripheral];
    
    espPeripheral.name = [advertisementData objectForKey:@"kCBAdvDataLocalName"];
    //    espPeripheral.name = peripheral.name;
    espPeripheral.rssi = RSSI.intValue;
    
    if (espPeripheral.name == nil) return;
    
    if (_filterContent && _filterContent.length > 0){
        if (!espPeripheral.name || [espPeripheral.name hasPrefix:_filterContent]){
            return;
        }
    }
    
    //    if (![espPeripheral.name.lowercaseString containsString:self.filterContent.lowercaseString]) return;
    
    NSDictionary* map = @{
        @"name":espPeripheral.name,
        @"address":peripheral.identifier.UUIDString,
        @"rssi": RSSI,
    };
    
    _peripheralDictionary[espPeripheral.uuid.UUIDString] = espPeripheral;
    [_channel invokeMethod:@"scanResult" arguments: map];
}

/**
 连接设备回调
 */
- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    _connected = YES;
    ///连接结果以gattPrepared方法为准
}
/**
 断开连接回调
 */
- (void) centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    _connected = NO;
    NSDictionary* map = @{@"code":[NSNumber numberWithInt:ESP_DISCONNECTED],};
    [_channel invokeMethod:@"connectDevice" arguments: map];
}
/**
 连接失败回调
 */
- (void) centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    _connected = NO;
    NSDictionary* map = @{@"code":[NSNumber numberWithInt:ESP_CONNECT_FAIL],};
    [_channel invokeMethod:@"connectDevice" arguments: map];
}

// 状态更新时调用
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    if (bluetoothEnabledResult){
        if (central.state == CBManagerStatePoweredOn){
            bluetoothEnabledResult(@(YES));
        } else {
            bluetoothEnabledResult(@(NO));
        }
        bluetoothEnabledResult = nil;
    }
    switch (central.state) {
        case CBManagerStateUnknown:{
            NSLog(@"未知状态");
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStateResetting:
        {
            NSLog(@"重置状态");
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStateUnsupported:
        {
            NSLog(@"不支持的状态");
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStateUnauthorized:
        {
            NSLog(@"未授权的状态");
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStatePoweredOff:
        {
            NSLog(@"关闭状态");
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStatePoweredOn:
        {
            NSLog(@"开启状态－可用状态");
            self.peripheralState = central.state;
            NSLog(@"%ld",(long)self.peripheralState);
            if (_isScaning){
                [self.centralManager scanForPeripheralsWithServices:nil options:nil];
            }
        }
            break;
        default:
            break;
    }
}

#pragma mark - BlufiDelegate

/**
 当扫描 Gatt 服务结束后调用该方法
 */
- (void)blufi:(BlufiClient *)client gattPrepared:(BlufiStatusCode)status service:(CBService *)service writeChar:(CBCharacteristic *)writeChar notifyChar:(CBCharacteristic *)notifyChar{
    NSLog(@"Blufi gattPrepared status:%d", status);
    if (status == StatusSuccess){
        ///成功
        _connected = YES;
        NSDictionary* map = @{@"code":[NSNumber numberWithInt:ESP_SUCCESS],};
        [_channel invokeMethod:@"connectDevice" arguments: map];
    } else {
        NSDictionary* map = @{@"code":[NSNumber numberWithInt:ESP_CONNECT_FAIL],};
        [_channel invokeMethod:@"connectDevice" arguments: map];
    }
}
/**
 收到 Device 的通知数据
 返回 NO 表示处理尚未结束，交给 BlufiClient 继续后续处理
 返回 YES 表示处理结束，后续将不再解析该数据，也不会调用回调方法
 */
- (BOOL)blufi:(BlufiClient *)client gattNotification:(NSData *)data packageType:(PackageType)pkgType subType:(SubType)subType{
    NSLog(@"gattNotification");
    return NO;
}
/**
 发送配置信息结果
 */
- (void)blufi:(BlufiClient *)client didPostConfigureParams:(BlufiStatusCode)status{
    NSLog(@"%@, status=%d", @"didPostConfigureParams", status);
}
/**
 收到Device状态信息 配网成功后也会走这个方法
 */
- (void)blufi:(BlufiClient *)client didReceiveDeviceStatusResponse:(BlufiStatusResponse *)response status:(BlufiStatusCode)status{
    NSLog(@"%@, status=%d, response=%@", @"didReceiveDeviceStatusResponse", status, response.getStatusInfo);
//    NSString * opMode;
//    switch (response.opMode) {
//        case OpModeNull:
//            opMode = @"NULL";
//            break;
//        case OpModeSta:
//            opMode = @"Station";
//            break;
//        case OpModeSoftAP:
//            opMode = @"SoftAP";
//            break;
//        case OpModeStaSoftAP:
//            opMode = @"Station/SoftAP";
//            break;
//        default:
//            break;
//    }
    
    NSDictionary *map = @{
        @"code": @(status == StatusSuccess && response.isStaConnectWiFi) ? @(ESP_SUCCESS) : @(ESP_DEVICE_STATUS_FAIL),
        @"opMode": [NSNumber numberWithInt:response.opMode],
        @"bssid": response.staBssid,
        @"ssid": response.staSsid,
        @"password": response.staPassword,
        @"message": response.getStatusInfo,
    };
    [_channel invokeMethod:@"deviceStatus" arguments: map];
}
/**
 收到Device扫描到的Wi-Fi信息
 */
- (void)blufi:(BlufiClient *)client didReceiveDeviceScanResponse:(NSArray<BlufiScanResponse *> *)scanResults status:(BlufiStatusCode)status{
    
    NSLog(@"%@, status=%d", @"didReceiveDeviceScanResponse", status);
    NSMutableArray<NSDictionary*> * resultList = [[NSMutableArray alloc]init];
    for (int i = 0; i < scanResults.count; i++) {
        BlufiScanResponse *scanResult = scanResults[i];
        NSLog(@"ssid:%@, rssi:%d, type:%d", scanResult.ssid, scanResult.rssi, scanResult.type);
        NSDictionary * map = @{
            @"ssid": scanResult.ssid,
            @"rssi": [NSNumber numberWithInt:scanResult.rssi],
            @"type": [NSNumber numberWithInt:scanResult.type],
        };
        [resultList addObject:map];
    }
    [_channel invokeMethod:@"scanWifi" arguments:resultList];
}
/**
 发送自定义数据的结果
 */
- (void)blufi:(BlufiClient *)client didPostCustomData:(NSData *)data status:(BlufiStatusCode)status{
    NSLog(@"%@, status=%d, data=%@", @"didPostCustomData", status, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
/**
 收到Device的自定义信息
 */
- (void)blufi:(BlufiClient *)client didReceiveCustomData:(NSData *)data status:(BlufiStatusCode)status{
    NSLog(@"%@, status=%d, data=%@", @"didReceiveCustomData", status, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}

@end
